<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="sy64n" id="sy64n"><span data-lake-id="ued5b52de" id="ued5b52de">典型回答</span></h1>
  <p data-lake-id="ub866b8c5" id="ub866b8c5"><br></p>
  <p data-lake-id="ud9069c40" id="ud9069c40"><span data-lake-id="u9916c055" id="u9916c055">Spring Event是Spring框架中的一种事件机制，它允许不同组件之间通过事件的方式进行通信。Spring框架中的事件机制建立在观察者模式的基础上，允许应用程序中的组件注册监听器来监听特定类型的事件，并在事件发生时执行相应的操作。</span></p>
  <p data-lake-id="u6f68b427" id="u6f68b427"><span data-lake-id="uf7b00195" id="uf7b00195">​</span><br></p>
  <p data-lake-id="u2a2b485c" id="u2a2b485c"><span data-lake-id="uc741d972" id="uc741d972">Spring Event的使用需要定义以下三个内容：</span></p>
  <p data-lake-id="ude46a149" id="ude46a149"><span data-lake-id="u27511be7" id="u27511be7">​</span><br></p>
  <ol list="ueddba1b8">
   <li fid="u8319d4af" data-lake-id="u8bc6e8ba" id="u8bc6e8ba"><span data-lake-id="u50684e06" id="u50684e06">事件（Event）：事件是一个普通的Java对象，用于封装关于事件发生的信息。通常，事件类会包含一些数据字段，以便监听器能够获取事件的相关信息。</span></li>
   <li fid="u8319d4af" data-lake-id="uc207895c" id="uc207895c"><span data-lake-id="ud2cd00cc" id="ud2cd00cc">事件发布者（Event Publisher）：事件发布者是负责触发事件并通知所有注册的监听器的组件。</span></li>
   <li fid="u8319d4af" data-lake-id="u3603f8cf" id="u3603f8cf"><span data-lake-id="u8e505c42" id="u8e505c42">事件监听器（Event Listener）：事件监听器是负责响应特定类型事件的组件。它们实现了一个接口或者使用注解来标识自己是一个事件监听器，并定义了在事件发生时需要执行的逻辑。</span></li>
  </ol>
  <p data-lake-id="udeb1ee52" id="udeb1ee52"><span data-lake-id="ud8b159bf" id="ud8b159bf">​</span><br></p>
  <h3 data-lake-id="nlJLl" id="nlJLl"><span data-lake-id="u9f393f6a" id="u9f393f6a">实现一个Spring Event</span></h3>
  <p data-lake-id="u392c1ba7" id="u392c1ba7"><br></p>
  <p data-lake-id="ufc5a3d48" id="ufc5a3d48"><span data-lake-id="u2b7d8b4f" id="u2b7d8b4f">假设我们在用户注册成功之后，需要发送一条欢迎短信，那么就可以通过事件来实现。</span></p>
  <p data-lake-id="u72386890" id="u72386890"><span data-lake-id="udf1b46e6" id="udf1b46e6">​</span><br></p>
  <p data-lake-id="u16236398" id="u16236398"><span data-lake-id="u48f73481" id="u48f73481">首先定义一个Event，需要继承ApplicationEvent类。</span></p>
  <p data-lake-id="u17a31cf8" id="u17a31cf8"><br></p>
  <pre lang="java"><code>
public class RegisterSuccessEvent extends ApplicationEvent {

    public RegisterSuccessEvent(RegisterInfo registerInfo) {
        super(registerInfo);
    }
}

</code></pre>
  <p data-lake-id="u448e9fb6" id="u448e9fb6"><span data-lake-id="u857466a8" id="u857466a8">​</span><br></p>
  <p data-lake-id="u336489b3" id="u336489b3"><span data-lake-id="u0c92097b" id="u0c92097b">在他的构造方法中，可以定义一个具体的事件内容。</span></p>
  <p data-lake-id="u0ad6a023" id="u0ad6a023"><span data-lake-id="ue7a8f176" id="ue7a8f176">​</span><br></p>
  <p data-lake-id="u8d09d1b5" id="u8d09d1b5"><span data-lake-id="uf2825c96" id="uf2825c96">然后再定义一个事件的监听者：</span></p>
  <p data-lake-id="ucc9704ae" id="ucc9704ae"><span data-lake-id="u9e296cc4" id="u9e296cc4">​</span><br></p>
  <pre lang="java"><code>

/**
 * 案件中心内部事件监听器
 *
 * @author Hollis
 */
@Component
public class RegisterEventListener {

    @EventListener(RegisterSuccessEvent.class)
    public void onApplicationEvent(RegisterSuccessEvent event) {
        RegisterInfo registerInfo = (RegisterInfo) event.getSource();

        //执行发送欢迎短信的逻辑
    }
}

</code></pre>
  <p data-lake-id="ub7366ac8" id="ub7366ac8"><span data-lake-id="u7c6d6757" id="u7c6d6757">​</span><br></p>
  <p data-lake-id="u4a63fe77" id="u4a63fe77"><span data-lake-id="u9aa5eed9" id="u9aa5eed9">​</span><br></p>
  <p data-lake-id="u5dc89341" id="u5dc89341"><span data-lake-id="ud3307a95" id="ud3307a95">以上这个监听器，在监听到一个RegisterSuccessEvent事件被发出来之后，会调用onApplicationEvent方法，我们就可以在这个方法中实现我们的发送欢迎短信的业务逻辑。</span></p>
  <p data-lake-id="uf916a406" id="uf916a406"><span data-lake-id="ue143f02b" id="ue143f02b">​</span><br></p>
  <p data-lake-id="u6fc5491e" id="u6fc5491e"><span data-lake-id="uabc5ef88" id="uabc5ef88">有了监听者，那么发送者也需要定义：</span></p>
  <p data-lake-id="u6b9774ca" id="u6b9774ca"><span data-lake-id="u8462f34f" id="u8462f34f">​</span><br></p>
  <pre lang="java"><code>
@Service
public class RegisterService{

  @Autowired
  protected ApplicationContext applicationContext;

	public RegisterResponse register(RegisterInfo registerInfo){

		//用户注册核心代码

  	//发送一个注册完成的事件
    applicationContext.publishEvent(new RegisterSuccessEvent(registerInfo));

  }

}
</code></pre>
  <p data-lake-id="uf849fb90" id="uf849fb90"><span data-lake-id="u50fbe71e" id="u50fbe71e"></span></p>
  <p data-lake-id="u1e8d42e2" id="u1e8d42e2"><span data-lake-id="uee447451" id="uee447451">在我们的RegisterService中，我们在用户注册成功之后，调用applicationContext.publishEvent即可把我们的注册成功事件广播出去了。</span></p>
  <p data-lake-id="u9d31c6dd" id="u9d31c6dd"><span data-lake-id="uf804159e" id="uf804159e">​</span><br></p>
  <p data-lake-id="u3929054d" id="u3929054d"><span data-lake-id="u5d61fb09" id="u5d61fb09">但是需要注意的是，默认情况下，Spring Event的调用时同步调用的。如果想要实现异步调用，也是支持的，最简单的方式就是借助@Async 注解：</span></p>
  <p data-lake-id="ua0214d66" id="ua0214d66"><span data-lake-id="u018f17b0" id="u018f17b0">​</span><br></p>
  <p data-lake-id="u8eb434f1" id="u8eb434f1"><span data-lake-id="u787be920" id="u787be920">修改监听器，增加@Async 注解：</span></p>
  <p data-lake-id="u12613b36" id="u12613b36"><br></p>
  <pre lang="java"><code>

/**
 * 案件中心内部事件监听器
 *
 * @author Hollis
 */
@Component
public class RegisterEventListener {

    @EventListener(RegisterSuccessEvent.class)
    @Async
    public void onApplicationEvent(RegisterSuccessEvent event) {
        RegisterInfo registerInfo = (RegisterInfo) event.getSource();

        //执行发送欢迎短信的逻辑
    }
}

</code></pre>
  <p data-lake-id="u49444e1b" id="u49444e1b"><span data-lake-id="uacd85dbd" id="uacd85dbd">​</span><br></p>
  <p data-lake-id="uaac9db2a" id="uaac9db2a"><span data-lake-id="u3940e8e9" id="u3940e8e9">并且需要开启对异步的支持，需要在Application.java中增加@EnableAsync</span></p>
  <p data-lake-id="ua5f0eb9d" id="ua5f0eb9d"><span data-lake-id="uf98d09dd" id="uf98d09dd"></span></p>
  <p data-lake-id="u64f4d8b9" id="u64f4d8b9"><span data-lake-id="uab71e8a1" id="uab71e8a1">但是，一般来说我不建议大家直接用@Async，最好是自定义线程池来实现异步：</span></p>
  <p data-lake-id="u09bed9be" id="u09bed9be"><span data-lake-id="u3672e882" id="u3672e882">​</span><br></p>
  <h1 data-lake-id="HfN9g" id="HfN9g"><span data-lake-id="u0412d644" id="u0412d644">扩展知识</span></h1>
  <p data-lake-id="uce7bd235" id="uce7bd235"><br></p>
  <h2 data-lake-id="YABEx" id="YABEx"><span data-lake-id="u95b1e07c" id="u95b1e07c">Spring Event带来的好处是什么</span></h2>
  <p data-lake-id="ub3809c36" id="ub3809c36"><br></p>
  <ol list="u52c9c28d">
   <li fid="u489d6c3f" data-lake-id="u3af23a2e" id="u3af23a2e"><span data-lake-id="u5f7117e5" id="u5f7117e5">代码解耦：通过使用事件机制，组件之间不需要直接互相依赖，从而减少了代码之间的耦合度。这使得代码更易于维护和扩展。</span></li>
  </ol>
  <p data-lake-id="ucaad545f" id="ucaad545f"><br></p>
  <ol list="u52c9c28d" start="2">
   <li fid="u489d6c3f" data-lake-id="u86dea966" id="u86dea966"><span data-lake-id="u4e5b9b35" id="u4e5b9b35">职责清晰：事件机制有助于将应用程序拆分为更小的模块，每个模块只关心要做的事儿，和关心自己需要监听的事件就行了。</span></li>
  </ol>
  <p data-lake-id="u29b17b42" id="u29b17b42"><br></p>
  <ol list="u52c9c28d" start="3">
   <li fid="u489d6c3f" data-lake-id="u2bbce872" id="u2bbce872"><span data-lake-id="uf22f225e" id="uf22f225e">异步处理：Spring Event机制支持异步事件处理，这意味着可以将事件的处理分发到不同的线程，提高了系统的响应性。</span></li>
  </ol>
  <p data-lake-id="ud3a77329" id="ud3a77329"><br></p>
  <ol list="u52c9c28d" start="4">
   <li fid="u489d6c3f" data-lake-id="u38fefdf5" id="u38fefdf5"><span data-lake-id="u70c63d86" id="u70c63d86">一对多：Spring Event是观察者模式的一种实现，他的一个事件可以有多个监听者，所以当我们有多个模块之间需要通信时，可以直接发一个事件出去，让监听者各自监听即可。</span></li>
  </ol>
 </body>
</html>